/*
 * MySqlPool.h
 *
 *  Created on: Jul 4, 2024
 *      Author: root
 */

#ifndef BSP_SQL_MYSQLPOOL_H_
#define BSP_SQL_MYSQLPOOL_H_
#include "MySql.h"

namespace bsp {

class MySqlPool {
private:
	MySqlPool(MySql &sql) :
			sql { sql } {
	}

	virtual ~MySqlPool() {
		sql.close();
	}

	MySql &sql;

	std::mutex mtx;
	std::condition_variable condition;

public:
	static MySqlPool* getInstance() {
		static MySql sql(DATABASE_HOST, DATABASE_PORT, DATABASE_USER,
		DATABASE_PWD, DATABASE_NAME, DATABASE_MAX_CONN);
		static MySqlPool pool(sql);

		static bool first = true;
		if (first) {
			sql.open();
		}
		first = false;

		return &pool;
	}

	MYSQL* getConn() {
		std::unique_lock<std::mutex> lock(mtx);
		if (sql.getAvalableCount() == 0) {
			condition.wait(lock);
		}
		return sql.getConn();
	}

	void freeConn(MYSQL *conn) {
		std::lock_guard<std::mutex> lock(mtx);
		sql.freeConn(conn);
		condition.notify_one();
	}

};

class SqlRAII {
private:
	MYSQL *sql;
public:
	SqlRAII() :
			sql { nullptr } {
	}

	~SqlRAII() {
		if (sql)
			MySqlPool::getInstance()->freeConn(sql);
	}

	MYSQL* getConn() {
		if (sql == nullptr)
			sql = MySqlPool::getInstance()->getConn();
		return sql;
	}
};

} /* namespace bsp */

#endif /* BSP_SQL_MYSQLPOOL_H_ */
